package com.easyfun.healthmagicbox.alarmclock;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Environment;
import android.util.Log;

public class AudioSpeexProcessor {
	protected static final String TAG = AlarmSettingActivity.class
			.getSimpleName();
	int frequency = 8000; // 11025;
	boolean isRecording = true;
	Speex speex = new Speex();
	AudioRecord audioRecord = null;
	private static int ENCODED_FRAME_SIZE = 38;
	public void stop()
	{
		if (audioRecord!=null)
			audioRecord.stop();
		isRecording = false;
	}

	public void record(String filename) {
		isRecording = true;
		int channelConfiguration = AudioFormat.CHANNEL_IN_FRONT;
		int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
		File file = new File(filename);

		//Environment.getExternalStorageDirectory()
		//.getAbsolutePath() + "/reverseme.pcm"

		// Delete any previous recording.
		if (file.exists())
			file.delete();

		// Create the new file.
		try {
			file.createNewFile();
		} catch (IOException e) {
			throw new IllegalStateException("Failed to create "
					+ file.toString());
		}
		DataOutputStream dos = null;
		try {
			// Create a DataOuputStream to write the audio data into the saved
			// file.
			OutputStream os = new FileOutputStream(file);
			BufferedOutputStream bos = new BufferedOutputStream(os);
			dos = new DataOutputStream(bos);

			// Create a new AudioRecord object to record the audio.
			int bufferSize = AudioRecord.getMinBufferSize(frequency,
					channelConfiguration, audioEncoding);
			audioRecord = new AudioRecord(
					MediaRecorder.AudioSource.MIC, frequency,
					channelConfiguration, audioEncoding, bufferSize);
			speex.init();
			short[] buffer = new short[bufferSize];
			long timestamp = System.currentTimeMillis();
			audioRecord.startRecording();
			//-----------------------------------
			short[] lin = new short[Speex.FRAME_SIZE];
			int offset = 0;
			//byte[] encoded = new byte[Speex.FRAME_SIZE];
			byte[] encoded = new byte[ENCODED_FRAME_SIZE];

			//-----------------------------------
			
			int totalbufferReadResult = 0;
			int linoffset = 0;
			while (isRecording) {
				int len = audioRecord.read(buffer, 0, bufferSize);
				if (len <=0)
					break;
				totalbufferReadResult = totalbufferReadResult + len;
				Log.d(TAG, "audio length:" + String.valueOf(totalbufferReadResult));
				for (int i = 0; i < len; i++)
				{
					lin[linoffset]=buffer[i];
					linoffset++;	
					if (linoffset == Speex.FRAME_SIZE - 1)
					{
						speex.encode(lin, offset, encoded, linoffset);						
						dos.write(encoded);
						linoffset = 0;
					}				
				}
			}
			if (linoffset > 0)
			{
				speex.encode(lin, offset, encoded, linoffset);
				dos.write(encoded);
			}
			
			
			long timestamp2 = System.currentTimeMillis();
			Log.d(TAG, "audio time length:" + String.valueOf(timestamp2-timestamp));

			audioRecord.stop();
			dos.close();
		} catch (Throwable t) {
			t.printStackTrace();
			Log.e(t.getMessage(), t.getStackTrace().toString());
			Log.e("AudioRecord", "Recording Failed");
		}finally
		{

			speex.close();
		}
	}

	public void play(String filename) {
		// Get the file we want to playback.
		//File file = new File(Environment.getExternalStorageDirectory()
		//		.getAbsolutePath() + "/reverseme.pcm");

		File file = new File(filename);
		// Get the length of the audio stored in the file (16 bit so 2 bytes per
		// short)
		// and create a short array to store the recorded audio.
		//int musicLength = (int) (file.length() / 2);
		int musicLength = (int) (file.length() * 12);
		short[] music = new short[musicLength];
		int musicoffset = 0;
		speex.init();
		try {
			// Create a DataInputStream to read the audio data back from the
			// saved file.
			InputStream is = new FileInputStream(file);
			BufferedInputStream bis = new BufferedInputStream(is);
			DataInputStream dis = new DataInputStream(bis);

			// Read the file into the music array.
			int i = 0;
			short[] lin = new short[Speex.FRAME_SIZE];
			byte[] encoded = new byte[ENCODED_FRAME_SIZE];
			while (dis.available() > 0) {
				encoded[i] = dis.readByte();					
				i++;
				if (i == ENCODED_FRAME_SIZE)
				{
					speex.decode(encoded, lin, ENCODED_FRAME_SIZE);
					for (int j=0;j<Speex.FRAME_SIZE;j++)
					{
						music[musicoffset] = lin[j];
						musicoffset++;
					}
					i = 0;
				}
			}

			// Close the input streams.
			dis.close();
			// Create a new AudioTrack object using the same parameters as the
			// AudioRecord
			// object used to create the file.
			AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
					frequency, AudioFormat.CHANNEL_CONFIGURATION_MONO,
					AudioFormat.ENCODING_PCM_16BIT, musicoffset * 2,
					AudioTrack.MODE_STREAM);
			// Start playback
			audioTrack.play();

			// Write the music buffer to the AudioTrack object
			audioTrack.write(music, 0, musicoffset);

			audioTrack.stop();

		} catch (Throwable t) {
			Log.e("AudioTrack", "Playback Failed");
		}finally
		{
			speex.close();
		}
	}
}
